#ifndef  __PK_BUFF_H__
#define  __PK_BUFF_H__

#include <pthread.h>
#include <string.h>

#include "ap_assert.h"
#include "types.h"
#include "net_hdr.h"
#include "mem_pool.h"
#include "list.h"

#if defined(CONFIG_NETWORK_WCDMA) && defined(CONFIG_NETWORK_CDMA2000)
#error "only one network could be defined"
#endif

#if defined(CONFIG_NETWORK_WCDMA)
struct gtphdr;
struct pdp_context;
#elif defined (CONFIG_NETWORK_CDMA2000)
 /* add wcdma2000 context type define here */
struct rad_context;
#elif defined (CONFIG_NETWORK_LAN)
 /* add wcdma2000 context type define here */
struct lu_context;
#else 
#error "network config not defined"
#endif

#define PKB_RESSAMBLE    0x01
#define HUGE_BUFFER_LEN  2960

struct reassemble_list {
    int count;
    struct list_head head;
};

struct reassemble_buf {
    struct list_head link;

#ifdef CONFIG_NETWORK_WCDMA
    struct iphdr *iphdr;
    struct gtphdr *gtphdr;
#endif

    struct iphdr  *iphdr_u;
    struct tcphdr *tcphdr_u;

    u32  next_seq;
    u32  timeout;
    u32  pkts;    /*howmany pakcets in buffer*/
    u16  len;
    u8   data[HUGE_BUFFER_LEN];
};

struct pk_buff {
    u8 *head;  /* pointer to raw data */
    u8 *data;  
    u16 len;
    u16 total; /* raw data length */
    
#ifdef CONFIG_NETWORK_WCDMA
    struct iphdr  *iphdr;
    struct gtphdr *gtphdr;
    struct pdp_context *context;
#endif

#ifdef CONFIG_NETWORK_CDMA2000
    struct rad_context *context;
#endif

#ifdef CONFIG_NETWORK_LAN
	struct lu_context *context;
#endif

    struct reassemble_buf *res_buf;

    u16 queue;  /* from which queue */
    u16 flag;
    char cb[256];
};

static inline u8 *pkb_pull(struct pk_buff *pkb, u16 len)
{
    /* AP_ASSERT(pkb->len > len); */
    if (pkb->len >= len) {
        pkb->len -= len;
        return pkb->data += len;
    } else
        return NULL;
}

/* ----------------------------------------------------------------- */
void reclaim_reassemble_buf(struct reassemble_list *list, u32 tm);
int  push_segment(struct reassemble_list *list, struct pk_buff *pkb);
int  reassemble_segment(struct reassemble_list *list, struct pk_buff *pkb);
int  pkt_reassemble_init();
void pkt_reassemble_clean();

extern struct mem_pool *reass_buf_pool;
static inline struct reassemble_buf *alloc_reassemble_buf() 
{
    struct reassemble_buf *buf = mem_pool_alloc(reass_buf_pool);
    if (buf) 
        memset(buf, 0, offsetof(struct reassemble_buf, data));
    return buf;
}

static inline void free_reassemble_buf(struct reassemble_buf *buf)
{
    mem_pool_free(buf);
}


#endif  /* __PK_BUFF_H__ */

